﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace Valentia.Kinection.DataTypes
{
    #region SkeletonJointVector CLASS
    /// <summary>
    /// Skeleton joint vector class.
    /// </summary>
    public class SkeletonJointVector
    {
        #region PROPERTIES
        /// <summary>
        /// Gets W value.
        /// </summary>
        public float W { get; private set; }

        /// <summary>
        /// Gets X value.
        /// </summary>
        public float X { get; private set; }

        /// <summary>
        /// Gets Y value.
        /// </summary>
        public float Y { get; private set; }

        /// <summary>
        /// Gets Z value.
        /// </summary>
        public float Z { get; private set; }
        #endregion

        #region CONSTRUCTOR
        /// <summary>
        /// Constrcutor.
        /// </summary>
        /// <param name="w">W</param>
        /// <param name="x"><X/param>
        /// <param name="y">Y</param>
        /// <param name="z">Z</param>
        public SkeletonJointVector(float w, float x, float y, float z)
        {
            this.W = w;
            this.X = x;
            this.Y = y;
            this.Z = z;
        }
        #endregion
    }
    #endregion

    #region SkeletonJointDepth CLASS
    /// <summary>
    /// Skeleton joint depth.
    /// </summary>
    public class SkeletonJointDepth
    {
        #region PROPERTIES
        /// <summary>
        /// Gets depth of X.
        /// </summary>
        public int DepthX { get; private set; }

        /// <summary>
        /// Gets depth of Y.
        /// </summary>
        public int DepthY { get; private set; }

        /// <summary>
        /// Gets depth value.
        /// </summary>
        public int DepthValue { get; private set; }

        /// <summary>
        /// Gets the player index.
        /// </summary>
        public int PlayerIndex { get; private set; }
        #endregion

        #region CONSTRUCTOR
        /// <summary>
        /// Conctructor.
        /// </summary>
        /// <param name="depthX">Depth of X.</param>
        /// <param name="depthY">Depth of Y.</param>
        /// <param name="depthValue">Depth value.</param>
        /// <param name="playerIndex">Player index.</param>
        public SkeletonJointDepth(int depthX, int depthY, int depthValue, int playerIndex)
        {
            this.DepthX = depthX;
            this.DepthY = depthY;
            this.DepthValue = depthValue;
            this.PlayerIndex = playerIndex;
        }
        #endregion
    }
    #endregion

    #region SkeletonJointInfo CLASS
    /// <summary>
    /// Skeleton joint information class
    /// </summary>
    public class SkeletonJointInfo
    {
        #region PROPERTIES
        /// <summary>
        /// Gets the joint ID.
        /// </summary>
        public SkeletonJointID JointID { get; private set; }

        /// <summary>
        /// Gets the x point of the joint mapped to color video image.
        /// </summary>
        public int ColorX { get; private set; }

        /// <summary>
        /// Gets the y point of joint mapped to color video image.
        /// </summary>
        public int ColorY { get; private set; }

        /// <summary>
        /// Gets the joint vector.
        /// </summary>
        public SkeletonJointVector Vector { get; private set; }

        /// <summary>
        /// Gets the joint depth.
        /// </summary>
        public SkeletonJointDepth JointDepth { get; private set; }
        #endregion

        #region CONSTRUCTOR
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="jointID">Joint ID.</param>
        /// <param name="colorX">X point of the joint mapped to color video image.</param>
        /// <param name="colorY">Y point of joint mapped to color video image.</param>
        /// <param name="vector">Joint vector.</param>
        /// <param name="jointDepth">Joint depth.</param>
        public SkeletonJointInfo(SkeletonJointID jointID, int colorX, int colorY, SkeletonJointVector vector, SkeletonJointDepth jointDepth)
        {
            this.JointID = jointID;
            this.ColorX = colorX;
            this.ColorY = colorY;
            this.Vector = vector;
            this.JointDepth = jointDepth;
        }
        #endregion

        #region METHODS
        /// <summary>
        /// Converts this instance into System.Drawing.Point.
        /// </summary>
        /// <returns>System.Drawing.Point instance</returns>
        public System.Drawing.Point ToPoint() { return new System.Drawing.Point(this.ColorX, this.ColorY); }
        #endregion
    }
    #endregion

    #region SkeletonJointCollection CLASS
    /// <summary>
    /// Skeleton joints collection class.
    /// </summary>
    public class SkeletonJointCollection : ReadOnlyCollection<SkeletonJointInfo> //ICollection<JointPoint>
    {
        #region DATA MEMBERS
        /// <summary>
        /// Contains the list of joints with information
        /// </summary>
        private Dictionary<SkeletonJointID, SkeletonJointInfo> mappedJoints;
        #endregion

        #region PROPERTIES
        /// <summary>
        /// Gets the tracking ID of skeleton. All joints in this collection are for the same skeleton.
        /// </summary>
        public int TrackingID { get; private set; }

        /// <summary>
        /// Gets the count of total joints.
        /// </summary>
        public int Count { get { return this.mappedJoints.Count; } }

        /// <summary>
        /// Gets the clipped edges of skeleton.
        /// </summary>
        public KinectClippedEdges ClippedEdges { get; private set; }

        /// <summary>
        /// Gets the skeleton joint by ID.
        /// </summary>
        /// <param name="ID">Skeleton joint ID</param>
        /// <returns>Skeleton joint.</returns>
        public SkeletonJointInfo this[SkeletonJointID ID] { get { return this.mappedJoints[ID]; } }
        #endregion

        #region CONSTRUCTOR
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="trackingID">Tracking ID of skeleton. All joints in this collection should be for this skeleton ID.</param>
        /// <param name="userIndex">User index of skeleton. All joints in this collection should be for this user index.</param>
        /// <param name="clippedEdges">Quality of skeleton.</param>
        /// <param name="mappedJoints">Contains the collection of joints mapped with joint ID.</param>
        public SkeletonJointCollection(int trackingID, KinectClippedEdges clippedEdges, Dictionary<SkeletonJointID, SkeletonJointInfo> mappedJoints)
            : base(new List<SkeletonJointInfo>(mappedJoints.Count))
        {
            this.mappedJoints = mappedJoints;
            this.TrackingID = trackingID;
            this.ClippedEdges = clippedEdges;

            foreach (SkeletonJointInfo joint in this.mappedJoints.Values) { base.Items.Add(joint); }
        }
        #endregion
    }
    #endregion
}